/**
 * Class correlation
 * 
 * @author Hussein Patwa
 * @date 10 April 2008
 * @version 3.0 Correlation functions common to local and global
 *          trending
 */
package trend;

import java.util.*;

@SuppressWarnings("all")
public class Correlation {
  /**
   * Constructor for correlation functions
   * 
   * @param correlationcoefficient Coefficient parameter
   * @param obsPred Treemap of predicted observations
   * @param sigmaX SigmaX from Utils applied to predicted observations
   * @param sigmaX2 SigmaX2 from Utils applied to predicted observations
   * @param sigmaY SigmaY from Utils applied to predicted observations
   * @param sigmaY2 SigmaY2 from Utils applied to predicted observations
   * @param numerator Root of ObsPred size x SigmaXY - (SigmaX x SigmaY)
   *          maths operation
   * @param denominator Root function similar to numerator raised to a
   *          power - maths operation
   * @param coefficient Numerator div Denominator - maths operation
   */
  double correlationCoefficient;

  public Correlation(TreeMap obsPred) {
    double sigmaX = Utils.sigmaX(obsPred.keySet());
    double sigmaX2 = Utils.sigmaXSquare(obsPred.keySet());
    double sigmaY = Utils.sigmaY(obsPred.values());
    double sigmaY2 = Utils.sigmaYSquare(obsPred.values());
    double sigmaXY = Utils.sigmaXY(obsPred);
    double numerator = (obsPred.size() * sigmaXY) - (sigmaX * sigmaY);
    double denominator = Math.sqrt(((obsPred.size() * sigmaX2) - Math
        .pow(sigmaX, 2)))
        * Math.sqrt(((obsPred.size() * sigmaY2) - Math.pow(sigmaY, 2)));
    correlationCoefficient = numerator / denominator;
  }

  /**
   * Get coefficient value
   * 
   * @return double
   */
  double getCorrelationCoefficient() {
    return correlationCoefficient;
  }

  // Sample example of Wikipedia Correlation pseudo code from
  // http://64.233.183.104/search?q=cache:f6bQ8-bRWQsJ:snippetsnap.com/snippets/4720-calculate-the-Pearson-s-correlation-in-JAVA+java+implementation+pearson+correlation&hl=en&ct=clnk&cd=3&gl=uk
  /**
   * Implementation of the Pearson moment correlation algorithm
   */
  public static double getPearsonCorrelation(double[] scores1,
      double[] scores2) {
    double result = 0;
    double sum_sq_x = 0;
    double sum_sq_y = 0;
    double sum_coproduct = 0;
    double mean_x = scores1[0];
    double mean_y = scores2[0];
    for (int i = 2; i < scores1.length + 1; i += 1) {
      double sweep = Double.valueOf(i - 1) / i;
      double delta_x = scores1[i - 1] - mean_x;
      double delta_y = scores2[i - 1] - mean_y;
      sum_sq_x += delta_x * delta_x * sweep;
      sum_sq_y += delta_y * delta_y * sweep;
      sum_coproduct += delta_x * delta_y * sweep;
      mean_x += delta_x / i;
      mean_y += delta_y / i;
    }
    double pop_sd_x = (double) Math.sqrt(sum_sq_x / scores1.length);
    double pop_sd_y = (double) Math.sqrt(sum_sq_y / scores1.length);
    double cov_x_y = sum_coproduct / scores1.length;
    result = cov_x_y / (pop_sd_x * pop_sd_y);
    return result;
  }

  /**
   * Test method for testing correlation functions
   * 
   * @param args Arguements to the method (data)
   * @return null
   */
  public static void main(String[] args) {
    // run the class for example data
    // first create a treemap object with example data
    TreeMap dat = new TreeMap();
    dat.put(new Double(1), new Double(8));
    dat.put(new Double(2), new Double(4));
    dat.put(new Double(3), new Double(6));
    // call correlation coefficient
    Correlation cor = new Correlation(dat);
    System.out.println(cor.getCorrelationCoefficient());
  }
}
